#include "auth_manager.h"
#include "base_log.h"
#include "base_utils.h"
#include "common_user_manager.h"
#include "web_server.h"
#include <random>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <openssl/evp.h>
#include <openssl/sha.h>

namespace El {
namespace Restful {

AuthManager &AuthManager::GetInstance()
{
    static AuthManager instance;
    return instance;
}

bool AuthManager::ValidateLogin(const std::string &username,
                                const std::string &password,
                                const std::string &device_id,
                                bool remember_me,
                                UserSession &session)
{
    // 从UserManager获取用户信息
    Common::UserInfo user_info;
    if (!Common::UserManager::GetInstance().GetUserInfo(username, user_info)) {
        LOG_ERROR("User not found: {}", username);
        return false;
    }

    // 检查用户是否启用
    if (!user_info.enabled) {
        LOG_ERROR("User account is disabled: {}", username);
        return false;
    }

    // 验证密码
    if (user_info.password != password) { // 注意：实际项目中应该使用加密的密码存储和验证
        LOG_ERROR("Invalid password for user: {}", username);
        return false;
    }

    // 生成新的会话
    session.username = username;
    session.device_id = device_id;
    session.role = user_info.role;

    // 生成新的token
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 255);
    unsigned char token_bytes[32];
    for (unsigned char &byte : token_bytes) {
        byte = static_cast<unsigned char>(dis(gen));
    }

    std::stringstream ss;
    for (unsigned char byte : token_bytes) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
    }
    session.access_token = "at_" + ss.str();

    ss.str("");
    ss.clear();
    for (unsigned char &byte : token_bytes) {
        byte = static_cast<unsigned char>(dis(gen));
    }
    for (unsigned char byte : token_bytes) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
    }
    session.refresh_token = "rt_" + ss.str();

    // 设置token过期时间
    auto current_time = std::chrono::system_clock::now();
    session.access_token_expiry = current_time + std::chrono::hours(1);
    session.refresh_token_expiry = current_time + (remember_me ? std::chrono::hours(720) : std::chrono::hours(24));

    // 保存会话信息
    active_sessions_[session.access_token] = session;
    refresh_token_map_[session.refresh_token] = session.access_token;

    LOG_INFO("User logged in successfully: {}", username);
    return true;
}

bool AuthManager::ValidateToken(const std::string &token, UserSession &session)
{
    auto it = active_sessions_.find(token);
    if (it == active_sessions_.end()) {
        LOG_WARN("Token not found: {}", token);
        return false;
    }

    session = it->second;

    // 检查token是否过期
    auto now = std::chrono::system_clock::now();
    if (now > session.access_token_expiry) {
        LOG_WARN("Token expired for user: {}", session.username);
        active_sessions_.erase(it);
        return false;
    }

    return true;
}

bool AuthManager::RefreshToken(const std::string &refresh_token, UserSession &session)
{
    // 查找refresh token对应的access token
    auto it = refresh_token_map_.find(refresh_token);
    if (it == refresh_token_map_.end()) {
        LOG_WARN("Refresh token not found: {}", refresh_token);
        return false;
    }

    // 查找会话信息
    auto session_it = active_sessions_.find(it->second);
    if (session_it == active_sessions_.end()) {
        LOG_WARN("Session not found for refresh token: {}", refresh_token);
        refresh_token_map_.erase(it);
        return false;
    }

    session = session_it->second;

    // 检查refresh token是否过期
    auto now = std::chrono::system_clock::now();
    if (now > session.refresh_token_expiry) {
        LOG_WARN("Refresh token expired for user: {}", session.username);
        refresh_token_map_.erase(it);
        active_sessions_.erase(session_it);
        return false;
    }

    // 生成新的access token
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 255);
    unsigned char token_bytes[32];
    for (unsigned char &byte : token_bytes) {
        byte = static_cast<unsigned char>(dis(gen));
    }

    std::stringstream ss;
    for (unsigned char byte : token_bytes) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
    }

    std::string old_access_token = session.access_token;
    session.access_token = "at_" + ss.str();
    session.access_token_expiry = now + std::chrono::hours(1);

    // 更新会话信息
    active_sessions_.erase(old_access_token);
    active_sessions_[session.access_token] = session;
    refresh_token_map_[refresh_token] = session.access_token;

    LOG_INFO("Token refreshed for user: {}", session.username);
    return true;
}

bool AuthManager::Logout(const std::string &access_token)
{
    auto it = active_sessions_.find(access_token);
    if (it == active_sessions_.end()) {
        LOG_WARN("Session not found for logout: {}", access_token);
        return false;
    }

    std::string username = it->second.username;
    active_sessions_.erase(it);

    // 清理相关的refresh token
    for (auto rt_it = refresh_token_map_.begin(); rt_it != refresh_token_map_.end();) {
        if (rt_it->second == access_token) {
            rt_it = refresh_token_map_.erase(rt_it);
        } else {
            ++rt_it;
        }
    }

    LOG_INFO("User logged out: {}", username);
    return true;
}

void AuthManager::CleanupExpiredSessions()
{
    auto now = std::chrono::system_clock::now();
    auto &web_server = WebServer::IHttpServer::GetInstance();

    // 清理过期的access token
    for (auto it = active_sessions_.begin(); it != active_sessions_.end();) {
        if (now > it->second.access_token_expiry) {
            LOG_DEBUG("Cleaning up expired session for user: {}", it->second.username);

            // 从web server中移除过期的token
            web_server.RemoveBearerToken(it->first);

            // 清理相关的refresh token
            for (auto rt_it = refresh_token_map_.begin(); rt_it != refresh_token_map_.end();) {
                if (rt_it->second == it->first) {
                    rt_it = refresh_token_map_.erase(rt_it);
                } else {
                    ++rt_it;
                }
            }
            it = active_sessions_.erase(it);
        } else {
            ++it;
        }
    }
}

} // namespace Restful
} // namespace El
